package edu.ccut.saturn.web.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.dom4j.Document;
import org.dom4j.Element;

import edu.ccut.saturn.component.IValidate;
import edu.ccut.saturn.component.SaturnComponentException;
import edu.ccut.saturn.component.ValidateManager;
import edu.ccut.saturn.component.ValidateResult;
import edu.ccut.saturn.component.xml.Dom4jUtils;

public class SaturnValidateServlet extends HttpServlet {

	private static final long serialVersionUID = -8940788230475664867L;

	private static final String __ERROR__ = "<datas><list><map><value></value></value key=\"message\">error</value></map></list></datas>";

	private static final String KEY_VALIDATE = "validate";


	private static final String KEY_VALIDATE_KEY = "key";
	private static final String KEY_VALIDATE_ARG = "arg";
	private static final String KEY_VALIDATE_ERRORINFOS = "errorInfos";
	private static final String KEY_VALIDATE_ERRORINFO = "errorInfo";
	private static final String LARGE_THAN = "__lt__";

	private static final String LESS_THAN = "__le__";

	public void doGet(HttpServletRequest request, HttpServletResponse response) {
		this.doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) {
		ValidateResult result = new ValidateResult();
		response.setContentType("text/xml;charset=UTF-8");
		try {
			String validateInfos = request.getParameter("xml");
			String value = request.getParameter("value");
			String flag = request.getParameter("flag");
			LinkedHashMap<String, String> validateInfoMap = new LinkedHashMap<String, String>();
			getValidateInfos(validateInfos, validateInfoMap);
			
			LinkedHashMap<String, Map<String,String>> errorInfos = getErrorInfosMap(validateInfos);
			
			String resultMessage = null;

			for (String validateKey : validateInfoMap.keySet()) {
				IValidate validate = ValidateManager.getInstance().getValidate(
						validateKey);
				//Lijialun
				validate.setErrorInfos(errorInfos.get(validateKey));
                //
				if (validate != null) {
					Object[] args = getArgs(validateInfoMap.get(validateKey));

					validate.validate(value, args, result);

				} else {
					resultMessage = __ERROR__;
					break;
				}
				if (flag == null || "false".equals(flag)) {

					if (!result.isSuccessful()) {
						break;
					}
				}
			}
			if (!__ERROR__.equals(resultMessage)) {
				resultMessage = result.toXml();
			}
			returnResult(response, resultMessage);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private LinkedHashMap<String, Map<String, String>> getErrorInfosMap(
			String validateInfos) throws SaturnComponentException {
		LinkedHashMap<String, Map<String, String>> returnMap = new LinkedHashMap<String, Map<String, String>>();

		StringReader stringReader = new StringReader(validateInfos);
		Document document = Dom4jUtils.getDocment(stringReader);
		Element root = document.getRootElement();
		List<Element> validateElements = root.elements(KEY_VALIDATE);

		if (validateElements != null && validateElements.size() > 0) {

			for (Element validateElement : validateElements) {
				String validateKey = validateElement
						.attributeValue(KEY_VALIDATE_KEY);

				Element errorInfosElement = validateElement
						.element(KEY_VALIDATE_ERRORINFOS);

				if (errorInfosElement != null) {
					List<Element> errorInfoElements = errorInfosElement.elements(KEY_VALIDATE_ERRORINFO);
					if(errorInfoElements !=null && errorInfoElements.size()>0){
						
						LinkedHashMap<String, String> errorInfos = new LinkedHashMap<String, String>();
						for (Element errorInfoElement : errorInfoElements) {
							errorInfos.put(errorInfoElement
									.attributeValue(KEY_VALIDATE_KEY),
									errorInfoElement.getTextTrim());
							
						}
						returnMap.put(validateKey, errorInfos);
					}
				}

			}
		}
		return returnMap;
	}

	private Object[] getArgs(String argStr) {

		if (argStr != null && !"".equals(argStr)) {
			List<String> args = new ArrayList<String>();
			int i = -1;

			while (i < argStr.length() - 1) {
				int index = argStr.indexOf(",", i + 1);

				if (index != -1) {
					String arg = argStr.substring(i + 1, index);
					arg = arg.replace(LARGE_THAN, ">");
					arg = arg.replace(LESS_THAN, "<");
					args.add(arg);
					i = index;
				}
			}
			if (args.size() > 0) {
				return args.toArray();
			}
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	private void getValidateInfos(String validateInfos,
			Map<String, String> validateInfoMap) throws SaturnComponentException {

		StringReader stringReader = new StringReader(validateInfos);
		Document document = Dom4jUtils.getDocment(stringReader);
		Element root = document.getRootElement();
		List<Element> validateElements = root.elements(KEY_VALIDATE);

		if (validateElements != null && validateElements.size() > 0) {

			for (Element validateElement : validateElements) {
				String validateKey = validateElement
						.attributeValue(KEY_VALIDATE_KEY);

				String arg = null;
				List<Element> argElements = validateElement
						.elements(KEY_VALIDATE_ARG);

				if (argElements != null && argElements.size() > 0) {
					StringBuffer buffer = new StringBuffer();

					for (Element argElement : argElements) {
						buffer.append(argElement.getTextTrim());
						buffer.append(",");
					}
					arg = buffer.toString();
				}
				validateInfoMap.put(validateKey, arg);
				
			}
		}
	}

	private void returnResult(HttpServletResponse response, String result)
			throws IOException {

		if (result == null) {
			result = "<datas><list><map><value></value><value key=\"message\">true</value></map></list></datas>";
		}
		response.setContentType("text/xml");
		response.setHeader("Cache-Control", "no-cache");
		PrintWriter out = response.getWriter();
		out.write("" + result);
	}
}
